﻿using Common.Infrastructure;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Common.EF
{
    public interface ICommonContextPool
    {
        Task<T> GetEntityAsync<T>(string id, string[] includes)
            where T : EntityBase, new();

        Task<T> GetEntityAsync<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, string[] contextCodes, string[] includes)
            where T : EntityBase, new();
        
        Task<List<T>> GetEntitiesAsync<T>(List<string> ids, string[] includes) 
            where T : EntityBase, new();

        Task<List<T>> GetEntitiesAsync<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, string[] contextCodes, string[] includes) 
            where T : EntityBase, new();

        Task<List<T>> GetOrderEntitiesAsync<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, string[] contextCodes, string[] includes)
           where T : EntityBase, new();
        
        Task<ApiPagedResult<T>> GetOrderPageEntitiesAsync<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, int startIndex, int pageSize, string[] contextCodes, string[] includes)
            where T : EntityBase, new();

        Task<int> GetCountAsync<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, string[] contextCodes)
          where T : EntityBase, new();

        Task<decimal> GetSumAsync<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Expression<Func<T, decimal>> sumExpression, string[] contextCodes) where T : EntityBase, new();

        Task<List<IGrouping<S, T>>> GetGroupByAsync<T, S>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Expression<Func<T, S>> groupByExpression, string[] contextCodes)
            where T : EntityBase, new();

        T GetEntity<T>(string id, string[] includes) 
            where T : EntityBase, new();

        T GetEntity<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, string[] contextCodes, string[] includes) 
            where T : EntityBase, new();

        List<T> GetEntities<T>(List<string> ids, string[] includes) 
            where T : EntityBase, new();

        List<T> GetEntities<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, string[] contextCodes, string[] includes) 
            where T : EntityBase, new();

        List<T> GetOrderEntities<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, string[] contextCodes, string[] includes)
          where T : EntityBase, new();

        ApiPagedResult<T> GetOrderPageEntities<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, int startIndex, int pageSize, string[] contextCodes, string[] includes)
           where T : EntityBase, new();

        int GetCount<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, string[] contextCodes)
             where T : EntityBase, new();

        decimal GetSum<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Expression<Func<T, decimal>> sumExpression, string[] contextCodes) where T : EntityBase, new();
        
        List<IGrouping<S, T>> GetGroupBy<T, S>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Expression<Func<T, S>> groupByExpression, string[] contextCodes)
             where T : EntityBase, new(); 

        void AddEntities<T>(List<T> entities)
            where T : EntityBase, new();

        void UpdateEntities<T>(List<T> entities, List<T> entitiesDb, params string[] updateProperies)
            where T : EntityBase, new();

        void DeleteEntity<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, string[] contextCodes)
           where T : EntityBase, new();

        void DeleteEntityByCommit<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, string[] contextCodes)
           where T : EntityBase, new();

        void UpdateEntitiesByByCommit<T>(DateTime? beginTime, DateTime? endTime, Expression<Func<T, bool>> predicate, Expression<Func<T, T>> updateExpression, string[] contextCodes)
           where T : EntityBase, new();

        void DeleteEntity<T>(List<string> ids)
            where T : EntityBase, new();

        string GetContextCodeById(string id);

        void Dispose();

        List<string> GetEntityIds(IDParam model);

        Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);

        int SaveChanges();

        Task DatabaseMigrateAsync(DateTime? beginTime, DateTime? endTime);

        void ExecuteReaderByContext(DateTime? beginTime, DateTime? endTime, CommandType commandType, string sql, ApiDbParameter[] parameters, Action<DbDataReader> readerAction, string[] contextCodes);
       
        void ExecuteNonQueryByContext(DateTime? beginTime, DateTime? endTime, string[] contextCodes, CommandType commandType, string sql, ApiDbParameter[] parameters);
         
        List<string> GetReadContextCodeByEntityName(DateTime? beginTime, DateTime? endTime, string entityName);
      
        List<string> GetContextCodeByEntityName(string entityName);
    }
}
